onmessage = function (e) {
    let { pixiArr,color,similarPoint,edgeLinePoint,stack,startX,startY,width,height,range } = e.data;
    
    /**
     * 颜色对比，接受在一定范围内的颜色
     * @param {Array[3]} current 当前需要判断的颜色值
     * @param {Array[3]} target 给定的颜色值
     * @param {number|Array(2)(3)} range  [min,max][[0.1,0.2,0.3],[0.4,0.5,0.6]] 容错大小 colorVal*(±range) >|< targetVal 
     */       
    function testColor(current, target, range) {
        if(Array.isArray(range)){ // 判断是否是二元数组，针对rgb三个颜色值进行调整
            // range = [[0.1,0.2,0.3],[0.4,0.5,0.6]];
            // 对RGB三个颜色的最大容错值和最小容错值进行细化
            for (let i = 0; i < 3; i++){
                if(target[i] === 0) {
                    target[i] = 1; // 排除起始点为0的情况
                }
                if( !((1 - range[0][i]) * target[i] <= current[i] && (1 + range[1][i]) * target[i] >= current[i])) return false
            }
        }else{
            for (let i = 0; i < 3; i++) {
                if (!((1 - range) * target[i] <= current[i] && (1 + range) * target[i] >= current[i])) return false;
            }
        }
        return true;
    }

     /** 八邻域泛洪 */
     function floodFill8(x, y) {
        // 8个方向
        let dx = [0, 1, 1, 1, 0, -1, -1, -1];
        let dy = [-1, -1, 0, 1, 1, 1, 0, -1];

        let map = {}; // 标识已经处理过的像素点，防止重复处理
        let similarMap = {} // 

        // 如果开始像素符合条件，则将它放入栈中并标识为已处理
        let cell = (x + y * width) * 4;  // 每四个值，为一个像素点 分别代表RGBA
        // 要用x，y坐标来确定像素点，可以用 x + y * width 避免取到同一个点

        // 判断当前点的颜色值是否符合需求，如果是则向堆栈中添中 
        //（因为第一次堆栈中没有值，所以在循环时候需要先执行一次）
        if (testColor([pixiArr[cell], pixiArr[cell + 1], pixiArr[cell + 2]], color, range)) {
            let firstPixi = `x${x}y${y}`; // `x${x}y${y}`是一个不会重复的唯一标识id
            map[firstPixi] = true;
            stack.push({ x , y });  // 向堆栈中推入这个符合条件的坐标
        } else return; // 否则直接结束

        let p; // position
        let opacity = 0.1;
        p = stack.pop();
        while ( p ) { // 获取栈顶待处理的符合条件的像素的x与y值
            cell = (p.x + p.y * width) * 4;  // 获取该坐标值
            // 如果设置了背景色，则直接替换成为背景色，如果没有设置，替换成透明色
            pixiArr[cell + 3] = 0;  // 使该坐标值透明化
            // 测试周围8个是否符合抠除条件
            for (let i = 0; i < 8; i++) {
                let nx = p.x + dx[i];
                let ny = p.y + dy[i];
                // 是否在范围内，并且没有被处理过
                if (nx >= 0 && nx < width && ny >= 0 && ny < height && !map[`x${nx}y${ny}`] && !similarMap[`x${nx}y${ny}`] ) {
                    cell = (nx + ny * width) * 4;
                    if (testColor([pixiArr[cell], pixiArr[cell + 1], pixiArr[cell + 2]], color, range)) {
                        map[`x${nx}y${ny}`] = true; // 标识此像素已被处理
                        // 没处理过则放入栈中
                        stack.push({
                            x: nx,
                            y: ny
                        }); // 推入堆栈后，等待下次执行取出并进行操作
                    }
                    else{
                        // cell = (nx + ny * width) * 4;
                        let newRange = [[],[]];
                        if(Array.isArray(range)){
                            for(let i = 0; i < 3; i++){
                                newRange[0][i] = range[0][i] + opacity + 0.8;
                                newRange[1][i] = range[1][i] + opacity + 0.3;
                            }
                        }else newRange = range + opacity + 0.3;
                        // 非高斯时查看边界
                        pixiArr[cell + 3] = 0;  // 使边界上的该坐标值透明化
                        // 拿到边界的像素坐标
                        similarMap[`x${nx}y${ny}`] = true; // 标识此像素已被处理
                        edgeLinePoint.push({
                            x : nx,
                            y : ny
                        })

                        if(testColor([pixiArr[cell], pixiArr[cell + 1], pixiArr[cell + 2]], color, newRange )){
                            pixiArr[cell + 3] = 64;  // 使该坐标值透明化
                            similarPoint.push({
                                x : nx,
                                y : ny
                            })
                        }
                    }
                }
            }
            p = stack.pop();
        }
    }
    floodFill8(startX, startY); // 从起始点开始进行八邻域算法
    postMessage( { pixiArr,color,similarPoint,edgeLinePoint,stack,startX,startY,width,height,range } );
}